package cn.lll.vuehouse.shiro;



import cn.lll.vuehouse.entity.RolePermission;
import cn.lll.vuehouse.entity.UserRole;
import cn.lll.vuehouse.mapper.PermissionMapper;
import cn.lll.vuehouse.mapper.RoleMapper;
import cn.lll.vuehouse.mapper.RolePermissionMapper;
import cn.lll.vuehouse.mapper.UserRoleMapper;
import cn.lll.vuehouse.utils.JWTUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;



//token验证  lalala
//直接继承AuthorizingRealm，能够继承到认证与授权功能。需强制重写两个方法
public class CustomerRealm extends AuthorizingRealm {

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private PermissionMapper permissionMapper;

    @Autowired
    private RolePermissionMapper rolePersMapper;


    //判断是否支持JWTToken
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JWTToken;
    }

    //授权方法
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        Object primaryPrincipal = principalCollection.getPrimaryPrincipal();
        System.out.println("======================授权方法=====================primaryPrincipal = " + primaryPrincipal);

        LambdaQueryWrapper<UserRole> lambda = new QueryWrapper<UserRole>().lambda();
        lambda.eq(UserRole::getUid,primaryPrincipal);


        List<Integer> rids = userRoleMapper.selectList(lambda).stream().map(userRole -> userRole.getRid()).collect(Collectors.toList());
        //角色字符串
        List<String> roles = roleMapper.selectBatchIds(rids).stream().map(role -> role.getRoleEn()).collect(Collectors.toList());

        //根据角色ID 查询权限字符串 role-p  pids
        LambdaQueryWrapper<RolePermission> lambda1 = new QueryWrapper<RolePermission>().lambda();
        lambda1.in(RolePermission::getRid,rids);

        List<Integer> pids = rolePersMapper.selectList(lambda1).stream().map(rolePers -> rolePers.getPid()).collect(Collectors.toList());

        //pids  查询权限字符串（permissions）
        List<String> permissions = permissionMapper.selectBatchIds(pids).stream().map(permission -> permission.getPermission()).collect(Collectors.toList());



        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();

        //添加角色权限
        simpleAuthorizationInfo.addRoles(roles);
        //添加权限字符串权限
        simpleAuthorizationInfo.addStringPermissions(permissions);
        return simpleAuthorizationInfo;
    }


    //认证方法 默认情况  认证通过 会将用户信息存储在session中，访问的是受限资源，被shiro提供的认证过滤器拦截
    //前后端分离    验证token真伪
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

        System.out.println("=================认证 doGetAuthenticationInfo()================");

        //判定token
        JWTToken jwtToken = (JWTToken) token;
        String tk = jwtToken.getToken();
        JWTUtil.veifyToken(tk);
        System.out.println("tk = " + tk);

        //获取用户id
        Map<String, Object> claim = JWTUtil.getClaim(tk);
        Object userId = claim.get("userId");
        System.out.println("userId = " + userId);

        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(userId,tk,this.getName());
        return simpleAuthenticationInfo;

    }
}
